#include "Main.h"

void UseSkill(long slot) //Uses skill on current target, 0-based
{
	byte* UseSkillFunctionPtr = Mem->GetAddress("UseSkillFunction");

	if(!UseSkillFunctionPtr)
		return;

	_asm {
		PUSH 0
		PUSH slot
		CALL UseSkillFunctionPtr
		ADD ESP,8
	}
}

void LootItem()
{
	byte* GetZByXYFunctionPtr = Mem->GetAddress("GetZByXYFunction");
	byte* WorldToScreenFunctionPtr = Mem->GetAddress("WorldToScreenFunction");

	float itemX, itemY, itemZ = 0.0f;
	int* int1array = new int[1];
	int* int4array = new int[4];

	__try {
		byte* CMonsterDropMgrPtr = (byte*)(*(dword*)Mem->GetAddress("CMonsterDropMgrPtr"));
		if(*(dword*)(CMonsterDropMgrPtr + 0x18) == *(dword*)(CMonsterDropMgrPtr + 0x1C)) //No drops available
			return;

		byte* pItemPack = (byte*)*(dword*)(*(dword*)(CMonsterDropMgrPtr + 0x18));
		itemX = *(float*)(pItemPack + 0x8);
		itemY = *(float*)(pItemPack + 0xC);

		byte* pTerrain = (byte*)(*(dword*)Mem->GetAddress("HR3DWorldPtr"));
		pTerrain = (byte*)(*(dword*)(pTerrain + 0x468));
		pTerrain = (byte*)(*(dword*)(pTerrain + 0x54));
		pTerrain = (byte*)(*(dword*)(pTerrain + 0xC4));
		
		_asm {
			PUSH int4array
			PUSH int1array
			PUSH 0
			PUSH 0
			PUSH itemY
			PUSH itemX
			MOV ECX,pTerrain
			CALL GetZByXYFunctionPtr
			FSTP DWORD PTR DS:[itemZ]
		}
	}
	__except(1) {
		return;
	}

	if(itemZ == 0.0f) //if GetZByXY didn't work
		return;

	delete int1array;
	delete int4array;

	float* inXYZ = new float[3];
	int* outX = new int[1];
	int* outY = new int[1];

	inXYZ[0] = itemX;
	inXYZ[1] = itemY;
	inXYZ[2] = itemZ;

	__try {
		byte* ScreenSizePtr = (byte*)(*(dword*)Mem->GetAddress("ScreenSizePtr"));
		int ScreenWidth = *(int*)(ScreenSizePtr + 0);
		int ScreenHeight = *(int*)(ScreenSizePtr + 4);

		byte* pHR3DCamera = (byte*)(*(dword*)Mem->GetAddress("HR3DPtr"));
		pHR3DCamera = (byte*)(*(dword*)(*(dword*)(pHR3DCamera) + 0x2BE1C));

		_asm {
			PUSH ScreenHeight
			PUSH ScreenWidth
			PUSH outY
			PUSH outX
			PUSH inXYZ
			MOV ECX,pHR3DCamera
			CALL WorldToScreenFunctionPtr
		}
	}
	__except(1) {
		return;
	}

	__try {
		byte* RButtonUpFunctionPtr = Mem->GetAddress("RButtonUpFunction");
		byte* MousePosPtr = (byte*)(*(dword*)Mem->GetAddress("MousePosPtr"));
		byte* CPlayerMgrPtr = (byte*)(*(dword*)Mem->GetAddress("CPlayerMgrPtr"));

		int argX = *outX;
		int argY = *outY;

		*(dword*)(MousePosPtr + 0) = argX;
		*(dword*)(MousePosPtr + 4) = argY;

		_asm {
			PUSH argY
			PUSH argX
			MOV ECX,CPlayerMgrPtr
			CALL RButtonUpFunctionPtr
		}
	}
	__except(1) {
		return;
	}

	delete [] inXYZ;
	delete [] outX;
	delete [] outY;
}

void DestroyItem(long index)
{
	byte* DestroyItemFunctionPtr = Mem->GetAddress("DestroyItemFunction");

	if(!DestroyItemFunctionPtr)
		return;

	DestroyItemStruct* destroyItem = new DestroyItemStruct;
	destroyItem->header = 15;
	destroyItem->zero = 0;
	destroyItem->constant = 17005;
	destroyItem->id = 0; //this is set by the function itself
	destroyItem->index = (word)index;

	_asm {
		PUSH destroyItem
		PUSH 1
		CALL DestroyItemFunctionPtr
	}

	delete destroyItem;
}

void RepairItems()
{
	byte* RepairItemsFunctionPtr = Mem->GetAddress("RepairItemsFunction");

	if(!RepairItemsFunctionPtr)
		return;

	_asm {
		PUSH 0
		PUSH 1
		CALL RepairItemsFunctionPtr
	}
}

unsigned long InternalGetTime()
{
	byte* InternalGetTimeFunctionPtr = Mem->GetAddress("InternalGetTimeFunction");
	dword retVal = 0;

	_asm {
		Call InternalGetTimeFunctionPtr
		MOV retVal,EAX
	}

	return retVal;
}

void MoveToMapXY(float X, float Y, unsigned long MapId)
{
	byte* MoveByMapXYFunctionPtr = Mem->GetAddress("MoveByMapXYFunction");
	byte* CAutoPathPtr;
	byte* MapIdPtr;

	__try {
		CAutoPathPtr = (byte*)(*(dword*)Mem->GetAddress("CAutoPathPtr"));
		MapIdPtr = (byte*)(*(dword*)Mem->GetAddress("MapIdPtr"));

		if(MapId == -1)
			MapId = *(dword*)MapIdPtr;
	}
	__except(1) {
		return;
	}

	float fX = (float)(X / 0.63999968); //Constant
	float fY = (float)(Y / 0.63999968);

	_asm {
		PUSH fY
		PUSH fX
		PUSH MapId
		MOV ECX,CAutoPathPtr
		CALL MoveByMapXYFunctionPtr
	}
}

void FollowPlayer(long playerId)
{
	byte* FollowPlayerFunctionPtr = Mem->GetAddress("FollowPlayerFunctionPtr");
	byte* CPlayerRolePtr;

	__try {
		CPlayerRolePtr = (byte*)(*(dword*)Mem->GetAddress("CPlayerRolePtr"));

		_asm {
			PUSH playerId
			MOV ECX,CPlayerRolePtr
			CALL FollowPlayerFunctionPtr
		}
	}
	__except(1) {
		return;
	}
}

unsigned long GetMapId()
{
	__try {
		return *(unsigned long*)(*(dword*)Mem->GetAddress("MapIdPtr"));
	}
	__except(1) {
		return NULL;
	}
}

void UseItemWrapper(unsigned long index)
{
	byte* SendPckFunctionPtr = Mem->GetAddress("SendPckFunction");
	byte* CNetworkInputPtr;
	SendPckStruct* pStruct = new SendPckStruct;

	__try {
		CNetworkInputPtr = (byte*)(*(dword*)Mem->GetAddress("CNetworkInputPtr"));

		pStruct->header = 0x12;
		pStruct->zero = 0;
		pStruct->op = 0x426A;
		pStruct->opEx = 0x0000;
		pStruct->id[0] = 0x00;
		pStruct->id[1] = (byte)index;
		pStruct->id[2] = 0xFF;
		pStruct->id[3] = 0xFF;

		_asm {
			PUSH pStruct
			MOV ECX,CNetworkInputPtr
			CALL SendPckFunctionPtr
		}
	}
	__except(1) {
		delete pStruct;
		return;
	}

	delete pStruct;
}

void AutoLootOnOff(bool bOnOff)
{
	byte* AutoLootPatch1Ptr = Mem->GetAddress("AutoLootPatch1");
	byte* AutoLootPatch2Ptr = Mem->GetAddress("AutoLootPatch2");
	byte* CombatAidPtr;

	if(!AutoLootPatch1Ptr || !AutoLootPatch2Ptr)
		return;

	DWORD dwOldProt = NULL;

	if(bOnOff = false)
	{
		VirtualProtect(AutoLootPatch1Ptr, 2, PAGE_EXECUTE_READWRITE, &dwOldProt);
		*(word*)(AutoLootPatch1Ptr) = 0x1074; // 74 10
		VirtualProtect(AutoLootPatch1Ptr, 2, dwOldProt, NULL);
		VirtualProtect(AutoLootPatch2Ptr, 2, PAGE_EXECUTE_READWRITE, &dwOldProt);
		*(word*)(AutoLootPatch2Ptr) = 0x1474; // 74 14
		VirtualProtect(AutoLootPatch2Ptr, 2, dwOldProt, NULL);
		return;
	}

	__try {
		CombatAidPtr = (byte*)(*(dword*)Mem->GetAddress("CombatAidPtr"));
		*(byte*)(CombatAidPtr + 0x9) = 1; //Pick up greens
		*(byte*)(CombatAidPtr + 0xA) = 1; //Pick up blues
		*(byte*)(CombatAidPtr + 0xB) = 1; //Pick up other items
		*(byte*)(CombatAidPtr + 0xC) = 1; //Pick up consumables/remedies
		*(byte*)(CombatAidPtr + 0xD) = 1; //Pick up gems/materials
		*(byte*)(CombatAidPtr + 0xE) = 1; //Pick up quest items
	}
	__except(1) {
		return;
	}

	VirtualProtect(AutoLootPatch1Ptr, 2, PAGE_EXECUTE_READWRITE, &dwOldProt);
	memset(AutoLootPatch1Ptr, 0x90, 2); //NOP 2 bytes
	VirtualProtect(AutoLootPatch1Ptr, 2, dwOldProt, NULL);

	VirtualProtect(AutoLootPatch2Ptr, 2, PAGE_EXECUTE_READWRITE, &dwOldProt);
	memset(AutoLootPatch2Ptr, 0x90, 2); //NOP 2 bytes
	VirtualProtect(AutoLootPatch2Ptr, 2, dwOldProt, NULL);
}